package models

import (
	"fmt"
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/orm"
	"smart_home/api/device"
	"time"
	"tools"
)

type Timing struct {
	Id       string `orm:"column(id);pk" json:"id" form:"id"`
	Sta      string `orm:"column(sta)" json:"sta" form:"sta"`
	Start    string `orm:"column(start)" json:"start" form:"start"`
	End      string `orm:"column(end)" json:"end" form:"end"`
	Wkocc    string `orm:"column(wkocc)" json:"wkocc" form:"wkocc"`
	State    int    `orm:"column(state)" json:"state" form:"state"`
	Loop     int    `orm:"column(loop)" json:"loop" form:"loop"`
	Time     int64  `orm:"column(time)" json:"time"`
	IsCharGe int    `orm:"column(is_charge)" json:"is_charge" form:"is_charge"`
}

func init() {
	orm.RegisterModel(new(Timing))
}

func (m *Timing) TableName() string {
	return "timing"
}

func NewTiming() *Timing {
	return &Timing{}
}

// 根据sta删除定时任务
func DelTimingBySta(sta string) error {
	sql := "DELETE FROM timing WHERE sta = ?"
	_, err := orm.NewOrm().Raw(sql).SetArgs(sta).Exec()
	if err != nil {
		logs.Warn(err)
		return err
	}
	return nil
}

// 根据id删除定时任务
func DelTimingById(id string) error {
	sql := "DELETE FROM timing WHERE id = ?"
	_, err := orm.NewOrm().Raw(sql).SetArgs(id).Exec()
	if err != nil {
		logs.Warn(err)
		return err
	}
	return nil
}

// 根据id找数据
func GetTimingById(id string) (*Timing, error) {
	timing := &Timing{Id: id}
	err := orm.NewOrm().Read(timing)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		logs.Warn("GetTimingById error:", err)
		return nil, err
	}
	return timing, nil
}

func GetTimingCountBySta(sta string) (int64, error) {
	return orm.NewOrm().QueryTable(NewTiming().TableName()).Filter("sta", sta).Count()
}

// 添加定时任务
func AddTiming(tm *Timing) bool {
	var (
		err error
		o   orm.Ormer
	)

	tm.Id = tools.GUUID()
	tm.Time = time.Now().Unix()
	tm.State = 1

	o = orm.NewOrm()
	o.Begin()
	// 数据入库
	if _, err = o.Insert(tm); err != nil {
		logs.Error("AddTiming err:", err)
		o.Rollback()
		return false
	}

	// 给设备发送命令
	if err = device.AddTiming(tm); err != nil {
		logs.Error("AddTiming err:", err)
		fmt.Println("rollback:", o.Rollback())
		return false
	}

	o.Commit()
	return true
}

// 更新定时任务
func UpdateTiming(tm *Timing) bool {
	var (
		err error
		o   orm.Ormer
	)

	o = orm.NewOrm()
	o.Begin()
	tm.Time = time.Now().Unix()
	fmt.Printf("%+v", tm)

	// 锁表
	timingData := &Timing{}
	sql := "select * from `timing` where `id` = ? for update"
	if err = o.Raw(sql).SetArgs(tm.Id).QueryRow(timingData); err != nil {
		logs.Error("UpdateTiming error:", err)
		o.Rollback()
		return false
	}

	// 数据入库
	if _, err = o.Update(tm); err != nil {
		logs.Error("UpdateTiming err:", err)
		o.Rollback()
		return false
	}

	// 给设备发送命令
	if err = device.UpdateTiming(tm); err != nil {
		logs.Error("UpdateTiming err:", err)
		fmt.Println("rollback:", o.Rollback())
		return false
	}

	o.Commit()
	return true
}

// 获取设备的所有定时任务
func GetAllTimingBySta(sta string) ([]*Timing, error) {
	var (
		err   error
		lists []*Timing
	)

	if _, err = orm.NewOrm().QueryTable(NewTiming().TableName()).Filter("sta", sta).All(&lists); err != nil {
		logs.Error("GetAllTimingByUid error:", err)
		return nil, err
	}
	if len(lists) == 0 {
		return nil, nil
	}

	return lists, nil
}

func DelTiming(tm *Timing) bool {
	var (
		err error
		o   orm.Ormer
		num int64
	)

	o = orm.NewOrm()
	o.Begin()
	// 给设备发送命令
	if err = device.DelTiming(tm); err != nil {
		logs.Error("DelTiming err:", err)
		o.Rollback()
		return false
	}

	// 数据入库
	if num, err = o.Delete(tm); err != nil {
		logs.Error("DelTiming error:", err)
		o.Rollback()
		return false
	}

	if num == 0 {
		o.Rollback()
		return false
	}

	o.Commit()
	return true
}
